Commit 8f7027a1 authored by Cezar Burlacu's avatar Cezar Burlacu Committed by Damien Lespiau
Browse files

series: Add a test_state field to revisions

We want to summarize the testing status of a series revision. Because of:

  https://docs.djangoproject.com/en/1.8/topics/db/aggregation/#combining-multiple-aggregations



we choose to cache the revision-wide test status on the revision
object and update it when a new test result is created.
Signed-off-by: default avatarCezar Burlacu <cezar.burlacu@intel.com>
Signed-off-by: default avatarDamien Lespiau <damien.lespiau@intel.com>
parent a1bdec36
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import migrations, models
def update_revision_test_state(apps, schema_editor):
SeriesRevision = apps.get_model("patchwork", "SeriesRevision")
TestResult = apps.get_model("patchwork", "TestResult")
query = SeriesRevision.objects.all()
for _, revision in enumerate(query.iterator()):
results = TestResult.objects.filter(revision=revision)
if results.count() > 0:
revision.test_state = max([r.state for r in results])
revision.save()
def noop(apps, schema_editor):
pass
class Migration(migrations.Migration):
dependencies = [
('patchwork', '0012_project_description'),
]
operations = [
migrations.AddField(
model_name='seriesrevision',
name='test_state',
field=models.SmallIntegerField(null=True, choices=[(0, b'pending'), (1, b'success'), (2, b'warning'), (3, b'failure')]),
),
migrations.RunPython(update_revision_test_state, noop),
]
......@@ -518,6 +518,8 @@ class SeriesRevision(models.Model):
root_msgid = models.CharField(max_length=255)
cover_letter = models.TextField(null = True, blank = True)
patches = models.ManyToManyField(Patch, through = 'SeriesRevisionPatch')
test_state = models.SmallIntegerField(choices=TestState.STATE_CHOICES,
null=True)
class Meta:
unique_together = [('series', 'version')]
......@@ -545,6 +547,7 @@ class SeriesRevision(models.Model):
new.pk = None
new.cover_letter = None
new.version = self.version + 1
new.test_state = None
new.save()
series = new.series
......@@ -567,6 +570,12 @@ class SeriesRevision(models.Model):
new.add_patch(p, order)
return new
def refresh_test_state(self):
results = TestResult.objects.filter(revision=self)
if results.count() > 0:
self.test_state = max([r.state for r in results])
self.save()
def __unicode__(self):
return "Revision " + str(self.version)
......
......@@ -127,10 +127,19 @@ class StateSerializer(serializers.ModelSerializer):
fields = ('id', 'name')
class SeriesSerializer(PatchworkModelSerializer):
test_state = serializers.SerializerMethodField('get_test_state')
def get_test_state(self, obj):
state = obj.latest_revision().test_state
if state is not None:
return dict(TestState.STATE_CHOICES)[state]
return state
class Meta:
model = Series
fields = ('id', 'project', 'name', 'n_patches', 'submitter',
'submitted', 'last_updated', 'version', 'reviewer')
'submitted', 'last_updated', 'version', 'reviewer',
'test_state')
read_only_fields = ('project', 'n_patches', 'submitter', 'submitted',
'last_updated', 'version')
expand_serializers = {
......
......@@ -34,6 +34,7 @@ from patchwork.tests.utils import TestSeries
from patchwork.models import (
Series, Patch, SeriesRevision, Test, TestResult, TestState
)
from patchwork.serializers import SeriesSerializer
entry_points = {
'/': {
......@@ -705,3 +706,29 @@ class TestResultTest(APITestBase):
self.assertEqual(email.subject,
u"✓ super test: success for " + test[1])
mail.outbox = []
def testRevisionTestStatus(self):
ss = SeriesSerializer()
self.assertEqual(TestResult.objects.all().count(), 0)
self.assertEqual(ss.get_test_state(self.series), None)
self._post_result(self.rev_url, "test1", 'pending')
self.assertEqual(ss.get_test_state(self.series), 'pending')
self._post_result(self.rev_url, "test2", 'success')
self.assertEqual(ss.get_test_state(self.series), 'success')
self._post_result(self.rev_url, "test3", 'warning')
self.assertEqual(ss.get_test_state(self.series), 'warning')
self._post_result(self.rev_url, "test4", 'failure')
self.assertEqual(ss.get_test_state(self.series), 'failure')
# Create a new revision
rev1 = SeriesRevision.objects.get(series=self.series, version=1)
rev2 = rev1.duplicate()
rev2.save()
self.assertEqual(self.series.revisions().count(), 2)
self.assertEqual(ss.get_test_state(self.series), None,
"'None' expected as a new revision must reset the testing state")
......@@ -359,8 +359,13 @@ class RevisionResultViewSet(viewsets.ViewSet, ResultMixin):
def create(self, request, series_pk, version_pk):
rev = get_object_or_404(SeriesRevision, series=series_pk,
version=version_pk)
return self.handle_test_results(request, rev, rev.series,
Q(revision=rev), {'revision': rev})
response = self.handle_test_results(request, rev, rev.series,
Q(revision=rev), {'revision': rev})
if response.status_code == status.HTTP_201_CREATED:
rev.refresh_test_state()
return response
def endpoint(endpoint):
"""Used to rename a method on a ViewSet"""
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment