From nobody Fri Oct 25 19:37:37 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of redhat.com designates 209.132.183.28 as permitted sender) client-ip=209.132.183.28; envelope-from=patchew-devel-bounces@redhat.com; helo=mx1.redhat.com; Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zoho.com: domain of redhat.com designates 209.132.183.28 as permitted sender) smtp.mailfrom=patchew-devel-bounces@redhat.com; dmarc=pass(p=none dis=none) header.from=redhat.com Return-Path: Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by mx.zohomail.com with SMTPS id 1521898665528480.67645624223326; Sat, 24 Mar 2018 06:37:45 -0700 (PDT) Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 92262369B7; Sat, 24 Mar 2018 13:37:43 +0000 (UTC) Received: from colo-mx.corp.redhat.com (colo-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.20]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 84BF687DC; Sat, 24 Mar 2018 13:37:43 +0000 (UTC) Received: from lists01.pubmisc.prod.ext.phx2.redhat.com (lists01.pubmisc.prod.ext.phx2.redhat.com [10.5.19.33]) by colo-mx.corp.redhat.com (Postfix) with ESMTP id 7A4F6181B9FB; Sat, 24 Mar 2018 13:37:43 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id w2ODbgsQ031761 for ; Sat, 24 Mar 2018 09:37:42 -0400 Received: by smtp.corp.redhat.com (Postfix) id 0F77B18EC1; Sat, 24 Mar 2018 13:37:42 +0000 (UTC) Received: from mx1.redhat.com (ext-mx08.extmail.prod.ext.phx2.redhat.com [10.5.110.32]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 0698D6090A for ; Sat, 24 Mar 2018 13:37:39 +0000 (UTC) Received: from mail-wr0-f181.google.com (mail-wr0-f181.google.com [209.85.128.181]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id CC02CC057F92 for ; Sat, 24 Mar 2018 13:37:28 +0000 (UTC) Received: by mail-wr0-f181.google.com with SMTP id p53so7154155wrc.10 for ; Sat, 24 Mar 2018 06:37:28 -0700 (PDT) Received: from donizetti.lan (94-36-194-48.adsl-ull.clienti.tiscali.it. [94.36.194.48]) by smtp.gmail.com with ESMTPSA id i78sm3854257wmc.32.2018.03.24.06.37.25 for (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Sat, 24 Mar 2018 06:37:25 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=sender:from:to:subject:date:message-id:in-reply-to:references; bh=7uipfwpqN4KQAtWvUOaMNXazbQKzKF5HAZQUPhTw2+w=; b=bZLe0YODGrcmq0mJKmzdiU8ERvS9P5tkoxe7VpNnpxgtq3xN48LKcEYxiAIe72RQC7 ZtRPmJHknBe5H0WcMfzBQxJnQ9WnlcNmy/LPmB6llLLoqskCNk5scOV1Oyf7YDwncCdo jmHOLaMyANjSdrEtwPmqFNOnRP8m5MypyoYLLem11L2YdJoLGreC8FuhPD5SO5luWZG2 Vqmvt5cK6d9N09MZTkvlGS5O0gM2yhokfHg9kQVawRHIXQRlO47hs2RNLCrUhhF1b4IW 2GFn2803eOeV4JJ2K8D4pS8JZIqfNQv1pTVg5HALrfJf1m09JEiQNwDFnsyT3h82k71V Xyag== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:from:to:subject:date:message-id :in-reply-to:references; bh=7uipfwpqN4KQAtWvUOaMNXazbQKzKF5HAZQUPhTw2+w=; b=pP1NyhNalnl5WGVKZIPpuCzJRjEgpD4klRgD8VrUsfPqXcaZl5wXZE0DZ7sn6+5nkV VtcbqSFpmxysWHRbK3v3K56T3s/3f54R7UAQKr2F5U8g9mRDzf/Agb3UzUY9MYApRy3Q QehJ4H8ZRfrQVEDMtEaHLEMILMnVLYd1OagpToRA0Rp3vu+M02u7B0ovVva38ZonfI69 uuweC1RkqN2YW2R3Vl9/QyDoypfHKsIX/UNrWuOiefQNBtQIM1iQ2LMU5WscAzcP85WZ sXoafJn2EVRPjNjONeNIU22DEgUj640ljydDBnuKfaeQbPVxunCHXfRojQFi0DdLSXVF bITQ== X-Gm-Message-State: AElRT7HfoHvysvL8j4UV0GhvUFoHRVDnTSAooLufpXqxLOxx1DoJuGN4 ad2Zr5Ys9it6+Z5lxkGoosISY5j/ X-Google-Smtp-Source: AG47ELsd8Yr1dTuqo7WnTKK7ywCLyuPVEjQAIXi4o7nkg/roX0ivS4QCAIYR+6e5uuvC1UjnSZiJ9A== X-Received: by 10.223.150.161 with SMTP id u30mr25168854wrb.151.1521898646734; Sat, 24 Mar 2018 06:37:26 -0700 (PDT) From: Paolo Bonzini To: patchew-devel@redhat.com Date: Sat, 24 Mar 2018 14:37:15 +0100 Message-Id: <20180324133719.6030-5-pbonzini@redhat.com> In-Reply-To: <20180324133719.6030-1-pbonzini@redhat.com> References: <20180324133719.6030-1-pbonzini@redhat.com> X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.32]); Sat, 24 Mar 2018 13:37:29 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.32]); Sat, 24 Mar 2018 13:37:29 +0000 (UTC) for IP:'209.85.128.181' DOMAIN:'mail-wr0-f181.google.com' HELO:'mail-wr0-f181.google.com' FROM:'paolo.bonzini@gmail.com' RCPT:'' X-RedHat-Spam-Score: 0.488 (DKIM_SIGNED, DKIM_VALID, FREEMAIL_FORGED_FROMDOMAIN, FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS, RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H2, SPF_PASS) 209.85.128.181 mail-wr0-f181.google.com 209.85.128.181 mail-wr0-f181.google.com X-RedHat-Possible-Forgery: Paolo Bonzini X-Scanned-By: MIMEDefang 2.78 on 10.5.110.32 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.13 X-loop: patchew-devel@redhat.com Subject: [Patchew-devel] [PATCH 4/8] rest: create separate results endpoint X-BeenThere: patchew-devel@redhat.com X-Mailman-Version: 2.1.12 Precedence: junk List-Id: Patchew development and discussion list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Sender: patchew-devel-bounces@redhat.com Errors-To: patchew-devel-bounces@redhat.com X-Scanned-By: MIMEDefang 2.79 on 10.5.11.11 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.30]); Sat, 24 Mar 2018 13:37:43 +0000 (UTC) X-ZohoMail-DKIM: fail (Header signature does not verify) X-ZohoMail: RDKM_2 RSF_0 Z_629925259 SPT_0 Content-Type: text/plain; charset="utf-8" In the REST API, each series can have one or more results. Right now results are synthesized from message properties which are set by the applier-report and tester-report API. In order to simplify the conversion to REST of those APIs (e.g. using POST, PUT or PATCH requests), move the results out of the SeriesSerializer and into their own collection. For now, the ViewSet is not model-based, but I am including paginator-like fields so that it should be possible to change it to a ModelViewSet in the future. Signed-off-by: Paolo Bonzini --- api/models.py | 7 +++-- api/rest.py | 72 ++++++++++++++++++++++++++++++++++++++++++++---= ---- api/urls.py | 5 ++++ mods/git.py | 17 ++++++------ mods/testing.py | 10 +++---- tests/test_git.py | 44 +++++++++++++++++++------------ tests/test_rest.py | 6 +++++ tests/test_testing.py | 33 ++++++++++++----------- 8 files changed, 133 insertions(+), 61 deletions(-) diff --git a/api/models.py b/api/models.py index 9b52693..6141ac1 100644 --- a/api/models.py +++ b/api/models.py @@ -595,14 +595,13 @@ class Module(models.Model): def __str__(self): return self.name =20 -class Result(namedtuple("Result", "name status log_url data")): +class Result(namedtuple("Result", "name status log_url obj data")): __slots__ =3D () =20 - def __new__(cls, name, status, log_url=3DNone, data=3DNone, request=3D= None): + def __new__(cls, name, status, obj, log_url=3DNone, data=3DNone, reque= st=3DNone): if log_url is not None and request is not None: log_url =3D request.build_absolute_uri(log_url) if status not in ('pending', 'success', 'failure'): raise ValueError("invalid value '%s' for status field" % statu= s) return super(cls, Result).__new__(cls, status=3Dstatus, log_url=3D= log_url, - data=3Ddata, name=3Dname) - + obj=3Dobj, data=3Ddata, name=3Dn= ame) diff --git a/api/rest.py b/api/rest.py index 0af1f30..1e2b774 100644 --- a/api/rest.py +++ b/api/rest.py @@ -8,17 +8,21 @@ # This work is licensed under the MIT License. Please see the LICENSE fil= e or # http://opensource.org/licenses/MIT. =20 +from collections import OrderedDict from django.contrib.auth.models import User +from django.http import Http404 from django.template import loader =20 from mod import dispatch_module_hook from .models import Project, Message from .search import SearchEngine -from rest_framework import permissions, serializers, viewsets, filters, mi= xins, renderers +from rest_framework import (permissions, serializers, viewsets, filters, + mixins, generics, renderers) from rest_framework.decorators import detail_route -from rest_framework.fields import SerializerMethodField +from rest_framework.fields import SerializerMethodField, CharField, JSONFi= eld from rest_framework.relations import HyperlinkedIdentityField from rest_framework.response import Response +import rest_framework =20 SEARCH_PARAM =3D 'q' =20 @@ -163,8 +167,8 @@ class SeriesSerializer(BaseMessageSerializer): =20 resource_uri =3D HyperlinkedMessageField(view_name=3D'series-detail') message =3D HyperlinkedMessageField(view_name=3D'messages-detail') + results =3D HyperlinkedMessageField(view_name=3D'results-list', lookup= _field=3D'series_message_id') total_patches =3D SerializerMethodField() - results =3D SerializerMethodField() =20 def __init__(self, *args, **kwargs): self.detailed =3D kwargs.pop('detailed', False) @@ -177,13 +181,6 @@ class SeriesSerializer(BaseMessageSerializer): fields=3Dfields, detailed=3Dself.detailed) return fields =20 - def get_results(self, message): - results =3D [] - request =3D self.context['request'] - dispatch_module_hook("rest_results_hook", request=3Drequest, - message=3Dmessage, results=3Dresults) - return {x.name: x._asdict() for x in results} - def get_total_patches(self, obj): return obj.get_total_patches() =20 @@ -316,3 +313,58 @@ class MessagesViewSet(ProjectMessagesViewSetMixin, serializer =3D BaseMessageSerializer(page, many=3DTrue, context=3Dself.get_serializer_c= ontext()) return self.get_paginated_response(serializer.data) + +# Results + +class HyperlinkedResultField(HyperlinkedIdentityField): + def get_url(self, result, view_name, request, format): + obj =3D result.obj + kwargs =3D {'projects_pk': obj.project_id, 'series_message_id': ob= j.message_id, + 'name': result.name} + return self.reverse(view_name, kwargs=3Dkwargs, request=3Drequest,= format=3Dformat) + +class ResultSerializer(serializers.Serializer): + resource_uri =3D HyperlinkedResultField(view_name=3D'results-detail') + name =3D CharField() + status =3D CharField() # one of 'failure', 'success', 'pending' + log_url =3D CharField(required=3DFalse) + data =3D JSONField(required=3DFalse) + +class SeriesResultsViewSet(viewsets.ViewSet, generics.GenericAPIView): + serializer_class =3D ResultSerializer + lookup_field =3D 'name' + lookup_value_regex =3D '[^/]+' + + def get_queryset(self): + return Message.objects.filter(project=3Dself.kwargs['projects_pk'], + message_id=3Dself.kwargs['series_mes= sage_id']) + + def get_results(self): + queryset =3D self.get_queryset() + try: + obj =3D queryset[0] + except IndexError: + raise Http404 + results =3D [] + dispatch_module_hook("rest_results_hook", request=3Dself.request, + obj=3Dobj, results=3Dresults) + return {x.name: x for x in results} + + def list(self, request, *args, **kwargs): + results =3D self.get_results().values() + serializer =3D self.get_serializer(results, many=3DTrue) + # Fake paginator response for forwards-compatibility, in case + # this ViewSet becomes model-based + return Response(OrderedDict([ + ('count', len(results)), + ('results', serializer.data) + ])) + + def retrieve(self, request, name, *args, **kwargs): + results =3D self.get_results() + try: + result =3D results[name] + except KeyError: + raise Http404 + serializer =3D self.get_serializer(result) + return Response(serializer.data) diff --git a/api/urls.py b/api/urls.py index 0a447f0..becabeb 100644 --- a/api/urls.py +++ b/api/urls.py @@ -37,11 +37,16 @@ projects_router.include_format_suffixes =3D False projects_router.register('series', rest.ProjectSeriesViewSet, base_name=3D= 'series') projects_router.register('messages', rest.MessagesViewSet, base_name=3D'me= ssages') =20 +results_router =3D NestedDefaultRouter(projects_router, 'series', lookup= =3D'series', trailing_slash=3DTrue) +results_router.include_format_suffixes =3D False +results_router.register('results', rest.SeriesResultsViewSet, base_name=3D= 'results') + schema_view =3D get_schema_view(title=3D'API schema') =20 urlpatterns =3D _build_urls() + [ url(r"v1/", include(router.urls)), url(r"v1/", include(projects_router.urls)), + url(r"v1/", include(results_router.urls)), url(r'^v1/schema/$', schema_view), # Use the base class's handler by default url(r".*", views.APIView.as_view()) diff --git a/mods/git.py b/mods/git.py index bf812df..13c3642 100644 --- a/mods/git.py +++ b/mods/git.py @@ -111,22 +111,23 @@ class GitModule(PatchewModule): raise Exception("Project git repo invalid: %s" % project_git) return upstream, branch =20 - def rest_results_hook(self, request, message, results): - l =3D message.get_property("git.apply-log") + def rest_results_hook(self, request, obj, results): + log =3D obj.get_property("git.apply-log") data =3D None - if l: - if message.get_property("git.apply-failed"): + if log: + if obj.get_property("git.apply-failed"): status =3D 'failure' else: - git_repo =3D message.get_property("git.repo") - git_tag =3D message.get_property("git.tag") + git_repo =3D obj.get_property("git.repo") + git_tag =3D obj.get_property("git.tag") data =3D {'repo': git_repo, 'tag': 'refs/tags/' + git_tag} status =3D 'success' - log_url =3D reverse("git-log", kwargs=3D{'series': message.mes= sage_id}) + log_url =3D reverse("git-log", kwargs=3D{'series': obj.message= _id}) else: status =3D 'pending' log_url =3D None - results.append(Result(name=3D'git', status=3Dstatus, log_url=3Dlog= _url, data=3Ddata, + results.append(Result(name=3D'git', obj=3Dobj, status=3Dstatus, + log_url=3Dlog_url, data=3Ddata, request=3Drequest)) =20 def prepare_message_hook(self, request, message, detailed): diff --git a/mods/testing.py b/mods/testing.py index cf22004..21942d5 100644 --- a/mods/testing.py +++ b/mods/testing.py @@ -276,19 +276,19 @@ class TestingModule(PatchewModule): return reverse("testing-get-prop", kwargs=3D{"project_or_series": obj.message_id}) =20 - def rest_results_hook(self, request, message, results): - for pn, p in message.get_properties().items(): + def rest_results_hook(self, request, obj, results): + for pn, p in obj.get_properties().items(): if not pn.startswith("testing.report."): continue tn =3D pn[len("testing.report."):] failed =3D not p["passed"] - log_url =3D self.reverse_testing_log(message, tn, request=3Dre= quest, html=3DFalse) + log_url =3D self.reverse_testing_log(obj, tn, request=3Dreques= t, html=3DFalse) passed_str =3D "failure" if failed else "success" =20 data =3D p.copy() del data['passed'] - results.append(Result(name=3D'testing.' + tn, status=3Dpassed_= str, log_url=3Dlog_url, - request=3Drequest, data=3Ddata)) + results.append(Result(name=3D'testing.' + tn, obj=3Dobj, statu= s=3Dpassed_str, + log_url=3Dlog_url, request=3Drequest, da= ta=3Ddata)) =20 def prepare_message_hook(self, request, message, detailed): if not message.is_series_head: diff --git a/tests/test_git.py b/tests/test_git.py index c2c98ae..8bff7d5 100755 --- a/tests/test_git.py +++ b/tests/test_git.py @@ -100,31 +100,41 @@ class GitTest(PatchewTestCase): self.repo + " patchew/20160628014747.20971-2-famz= @redhat.com") =20 def test_rest_need_apply(self): - resp =3D self.apply_and_retrieve("0013-foo-patch.mbox.gz", self.p.= id, - "20160628014747.20971-1-famz@redhat= .com") - self.assertEqual(resp.data['results']['git']['status'], 'pending') + self.cli_import("0013-foo-patch.mbox.gz") + MESSAGE_ID =3D '20160628014747.20971-1-famz@redhat.com' + resp =3D self.api_client.get('%sseries/%s/results/git/' % (self.PR= OJECT_BASE, MESSAGE_ID)) + self.assertEqual(resp.data['status'], 'pending') + self.assertEqual(resp.data['log_url'], None) =20 def test_rest_apply_failure(self): self.cli_import("0014-bar-patch.mbox.gz") self.do_apply() - resp =3D self.api_client.get(self.REST_BASE + 'series/?q=3Dproject= :QEMU') - self.assertEqual(resp.data['results'][0]['is_complete'], True) - self.assertEqual(resp.data['results'][0]['results']['git']['status= '], 'failure') - self.assertEqual('repo' in resp.data['results'][0]['results']['git= '], False) - self.assertEqual('tag' in resp.data['results'][0]['results']['git'= ], False) - log =3D self.client.get(resp.data['results'][0]['results']['git'][= 'log_url']) - self.assertEquals(log.status_code, 200) + MESSAGE_ID =3D '20160628014747.20971-2-famz@redhat.com' + resp =3D self.api_client.get('%sseries/%s/' % (self.PROJECT_BASE, = MESSAGE_ID)) + self.assertEqual(resp.data['is_complete'], True) + + resp =3D self.api_client.get('%sseries/%s/results/' % (self.PROJEC= T_BASE, MESSAGE_ID)) + self.assertEqual(resp.data['results'][0]['name'], 'git') + + resp =3D self.api_client.get('%sseries/%s/results/git/' % (self.PR= OJECT_BASE, MESSAGE_ID)) + self.assertEqual(resp.data['status'], 'failure') + self.assertEqual('repo' in resp.data, False) + self.assertEqual('tag' in resp.data, False) + log =3D self.client.get(resp.data['log_url']) + self.assertEqual(log.status_code, 200) =20 def test_rest_apply_success(self): self.cli_import("0013-foo-patch.mbox.gz") self.do_apply() - resp =3D self.api_client.get(self.REST_BASE + 'series/?q=3Dproject= :QEMU') - self.assertEqual(resp.data['results'][0]['is_complete'], True) - self.assertEqual(resp.data['results'][0]['results']['git']['status= '], 'success') - self.assertEqual(resp.data['results'][0]['results']['git']['data']= ['repo'], self.repo) - self.assertEqual(resp.data['results'][0]['results']['git']['data']= ['tag'], "refs/tags/patchew/20160628014747.20971-1-famz@redhat.com") - log =3D self.client.get(resp.data['results'][0]['results']['git'][= 'log_url']) - self.assertEquals(log.status_code, 200) + MESSAGE_ID =3D '20160628014747.20971-1-famz@redhat.com' + resp =3D self.api_client.get('%sseries/%s/' % (self.PROJECT_BASE, = MESSAGE_ID)) + self.assertEqual(resp.data['is_complete'], True) + resp =3D self.api_client.get('%sseries/%s/results/git/' % (self.PR= OJECT_BASE, MESSAGE_ID)) + self.assertEqual(resp.data['status'], 'success') + self.assertEqual(resp.data['data']['repo'], self.repo) + self.assertEqual(resp.data['data']['tag'], "refs/tags/patchew/2016= 0628014747.20971-1-famz@redhat.com") + log =3D self.client.get(resp.data['log_url']) + self.assertEqual(log.status_code, 200) =20 if __name__ =3D=3D '__main__': main() diff --git a/tests/test_rest.py b/tests/test_rest.py index 28ca10b..391714f 100755 --- a/tests/test_rest.py +++ b/tests/test_rest.py @@ -189,6 +189,12 @@ class RestTest(PatchewTestCase): resp =3D self.api_client.get(self.REST_BASE + 'projects/12345/seri= es/') self.assertEqual(resp.data['count'], 0) =20 + def test_series_results_list(self): + resp1 =3D self.apply_and_retrieve('0001-simple-patch.mbox.gz', + self.p.id, '20160628014747.20971-1-= famz@redhat.com') + resp =3D self.api_client.get(resp1.data['results']) + self.assertEqual(resp.data['count'], len(resp.data['results'])) + def test_series_search(self): resp1 =3D self.apply_and_retrieve('0004-multiple-patch-reviewed.mb= ox.gz', self.p.id, '1469192015-16487-1-git= -send-email-berrange@redhat.com') diff --git a/tests/test_testing.py b/tests/test_testing.py index 0897bbc..369a806 100755 --- a/tests/test_testing.py +++ b/tests/test_testing.py @@ -93,41 +93,40 @@ class TestingTest(PatchewTestCase): capabilities=3D[]) self.assertFalse(td) =20 - def test_rest_basic(self): - resp =3D self.api_client.get(self.PROJECT_BASE + 'series/' + self.= msg.message_id + '/') - self.assertEquals('testing.tests' in resp.data['results'], False) - def test_rest_done_success(self): self.msg_testing_done(log=3D'everything good!', passed=3DTrue) - resp =3D self.api_client.get(self.PROJECT_BASE + 'series/' + self.= msg.message_id + '/') - self.assertEquals(resp.data['results']['testing.tests']['status'],= 'success') - log =3D self.client.get(resp.data['results']['testing.tests']['log= _url']) + resp =3D self.api_client.get('%sseries/%s/results/testing.tests/' = % (self.PROJECT_BASE, self.msg.message_id)) + self.assertEquals(resp.data['status'], 'success') + log =3D self.client.get(resp.data['log_url']) self.assertEquals(log.status_code, 200) self.assertEquals(log.content, b'everything good!') =20 def test_rest_done_failure(self): - self.msg_testing_done(log=3D'sorry no good', passed=3DFalse) - resp =3D self.api_client.get(self.PROJECT_BASE + 'series/' + self.= msg.message_id + '/') - self.assertEquals(resp.data['results']['testing.tests']['status'],= 'failure') - log =3D self.client.get(resp.data['results']['testing.tests']['log= _url']) + self.msg_testing_done(log=3D'sorry no good', passed=3DFalse, rando= m_stuff=3D'xyz') + resp =3D self.api_client.get('%sseries/%s/results/testing.tests/' = % (self.PROJECT_BASE, self.msg.message_id)) + self.assertEquals(resp.data['status'], 'failure') + self.assertEquals(resp.data['data']['random_stuff'], 'xyz') + log =3D self.client.get(resp.data['log_url']) self.assertEquals(log.status_code, 200) self.assertEquals(log.content, b'sorry no good') =20 def test_api_report_success(self): self.api_login() msgid =3D self.msg_testing_report(log=3D'everything good!', passed= =3DTrue) - resp =3D self.api_client.get(self.PROJECT_BASE + 'series/' + self.= msg.message_id + '/') - self.assertEquals(resp.data['results']['testing.a']['status'], 'su= ccess') - log =3D self.client.get(resp.data['results']['testing.a']['log_url= ']) + resp =3D self.api_client.get('%sseries/%s/results/testing.a/' % (s= elf.PROJECT_BASE, self.msg.message_id)) + self.assertEquals(resp.data['data']['is_timeout'], False) + self.assertEquals(resp.data['status'], 'success') + log =3D self.client.get(resp.data['log_url']) self.assertEquals(log.status_code, 200) self.assertEquals(log.content, b'everything good!') =20 def test_api_report_failure(self): self.api_login() msgid =3D self.msg_testing_report(log=3D'sorry no good', passed=3D= False) - resp =3D self.api_client.get(self.PROJECT_BASE + 'series/' + self.= msg.message_id + '/') - self.assertEquals(resp.data['results']['testing.a']['status'], 'fa= ilure') - log =3D self.client.get(resp.data['results']['testing.a']['log_url= ']) + resp =3D self.api_client.get('%sseries/%s/results/testing.a/' % (s= elf.PROJECT_BASE, self.msg.message_id)) + self.assertEquals(resp.data['data']['is_timeout'], False) + self.assertEquals(resp.data['status'], 'failure') + log =3D self.client.get(resp.data['log_url']) self.assertEquals(log.status_code, 200) self.assertEquals(log.content, b'sorry no good') =20 --=20 2.16.2 _______________________________________________ Patchew-devel mailing list Patchew-devel@redhat.com https://www.redhat.com/mailman/listinfo/patchew-devel