diff options
Diffstat (limited to 'WebKitTools/QueueStatusServer')
6 files changed, 107 insertions, 25 deletions
diff --git a/WebKitTools/QueueStatusServer/__init__.py b/WebKitTools/QueueStatusServer/__init__.py new file mode 100644 index 0000000..2346c23 --- /dev/null +++ b/WebKitTools/QueueStatusServer/__init__.py @@ -0,0 +1,29 @@ +# Required for Python to search this directory for module files + +# This __init__.py makes unit testing easier by allowing us to treat the entire server as one big module. +# This file is only accessed when not on AppEngine itself. + +# Make sure that this module will load in that case by including paths to +# the default Google AppEngine install. + + +def fix_sys_path(): + import sys + import os + + # AppEngine imports a bunch of google-specific modules. Thankfully the dev_appserver + # knows how to do the same. Re-use the dev_appserver fix_sys_path logic to import + # all the google.appengine.* stuff so we can run under test-webkitpy + sys.path.append("/usr/local/google_appengine") + import dev_appserver + dev_appserver.fix_sys_path() + + # test-webkitpy adds $WEBKIT/WebKitTools to the sys.path and imports + # QueueStatusServer to run all the tests. However, when AppEngine runs + # our code QueueStatusServer is the root (and thus in the path). + # Emulate that here for test-webkitpy so that we can import "model." + # not "QueueStatusServer.model.", etc. + sys.path.append(os.path.dirname(__file__)) + + +fix_sys_path() diff --git a/WebKitTools/QueueStatusServer/handlers/queuestatus.py b/WebKitTools/QueueStatusServer/handlers/queuestatus.py index 5c31537..54c0fdd 100644 --- a/WebKitTools/QueueStatusServer/handlers/queuestatus.py +++ b/WebKitTools/QueueStatusServer/handlers/queuestatus.py @@ -26,11 +26,12 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +import itertools + from google.appengine.ext import webapp from google.appengine.ext.webapp import template from model.queues import Queue - from model import queuestatus @@ -49,6 +50,12 @@ class QueueStatus(webapp.RequestHandler): }) return rows + def _grouping_key_for_status(self, status): + return "%s-%s" % (status.active_patch_id, status.bot_id) + + def _build_status_groups(self, statuses): + return [list(group) for key, group in itertools.groupby(statuses, self._grouping_key_for_status)] + def get(self, queue_name): queue_name = queue_name.lower() queue = Queue.queue_with_name(queue_name) @@ -56,24 +63,10 @@ class QueueStatus(webapp.RequestHandler): self.error(404) return - status_groups = [] - last_patch_id = None - synthetic_patch_id_counter = 0 - statuses = queuestatus.QueueStatus.all().filter("queue_name =", queue.name()).order("-date").fetch(15) - for status in statuses: - patch_id = status.active_patch_id - if not patch_id or last_patch_id != patch_id: - status_group = [] - status_groups.append(status_group) - else: - status_group = status_groups[-1] - status_group.append(status) - last_patch_id = patch_id - template_values = { "display_queue_name": queue.display_name(), "work_item_rows": self._rows_for_work_items(queue), - "status_groups": status_groups, + "status_groups": self._build_status_groups(statuses), } self.response.out.write(template.render("templates/queuestatus.html", template_values)) diff --git a/WebKitTools/QueueStatusServer/handlers/queuestatus_unittest.py b/WebKitTools/QueueStatusServer/handlers/queuestatus_unittest.py new file mode 100644 index 0000000..a5ae844 --- /dev/null +++ b/WebKitTools/QueueStatusServer/handlers/queuestatus_unittest.py @@ -0,0 +1,62 @@ +# Copyright (C) 2010 Google, Inc. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Research in Motion Ltd. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +import unittest + +from handlers.queuestatus import QueueStatus +from model.queues import Queue + + +class MockStatus(object): + def __init__(self, patch_id, bot_id): + self.active_patch_id = patch_id + self.bot_id = bot_id + + +class QueueStatusTest(unittest.TestCase): + def test_build_status_groups(self): + queue_status = QueueStatus() + statuses = [ + MockStatus(1, "foo"), + MockStatus(1, "foo"), + MockStatus(2, "foo"), + MockStatus(1, "foo"), + MockStatus(1, "bar"), + MockStatus(1, "foo"), + ] + groups = queue_status._build_status_groups(statuses) + self.assertEqual(len(groups), 5) + self.assertEqual(groups[0], statuses[0:2]) + self.assertEqual(groups[1], statuses[2:3]) + self.assertEqual(groups[2], statuses[3:4]) + self.assertEqual(groups[3], statuses[4:5]) + self.assertEqual(groups[4], statuses[5:6]) + + +if __name__ == '__main__': + unittest.main() diff --git a/WebKitTools/QueueStatusServer/model/workitems.py b/WebKitTools/QueueStatusServer/model/workitems.py index fae6830..772fc39 100644 --- a/WebKitTools/QueueStatusServer/model/workitems.py +++ b/WebKitTools/QueueStatusServer/model/workitems.py @@ -52,6 +52,7 @@ class WorkItems(db.Model, QueuePropertyMixin): work_items.item_ids.append(attachment_id) work_items.put() + # Because this uses .key() self.is_saved() must be True or this will throw NotSavedError. def add_work_item(self, attachment_id): db.run_in_transaction(self._unguarded_add, self.key(), attachment_id) @@ -63,5 +64,6 @@ class WorkItems(db.Model, QueuePropertyMixin): work_items.item_ids.remove(attachment_id) work_items.put() + # Because this uses .key() self.is_saved() must be True or this will throw NotSavedError. def remove_work_item(self, attachment_id): db.run_in_transaction(self._unguarded_remove, self.key(), attachment_id) diff --git a/WebKitTools/QueueStatusServer/model/workitems_unittest.py b/WebKitTools/QueueStatusServer/model/workitems_unittest.py index d53302e..b1ff1d3 100644 --- a/WebKitTools/QueueStatusServer/model/workitems_unittest.py +++ b/WebKitTools/QueueStatusServer/model/workitems_unittest.py @@ -40,14 +40,6 @@ class WorkItemsTest(unittest.TestCase): self.assertEquals(items.display_position_for_attachment(1), 2) self.assertEquals(items.display_position_for_attachment(3), None) - def test_remove_work_item(self): - items = WorkItems() - items.item_ids = [0, 1, 2] - items.remove_work_item(0) - self.assertEqual(items.item_ids, [1, 2]) - items.remove_work_item(4) # Should not throw - self.assertEqual(items.item_ids, [1, 2]) - if __name__ == '__main__': unittest.main() diff --git a/WebKitTools/QueueStatusServer/templates/includes/singlequeuestatus.html b/WebKitTools/QueueStatusServer/templates/includes/singlequeuestatus.html index 075cd39..0adbfbd 100644 --- a/WebKitTools/QueueStatusServer/templates/includes/singlequeuestatus.html +++ b/WebKitTools/QueueStatusServer/templates/includes/singlequeuestatus.html @@ -1,4 +1,8 @@ -<span class="status-date">{{ status.date|timesince }} ago</span> +<span class="status-date">{{ status.date|timesince }} ago +{% if status.bot_id %} +({{ status.bot_id }}) +{% endif %} +</span> <span class="status-message">{{ status.message|force_escape|urlize|webkit_linkify|safe }}</span> {% if status.results_file %} <span class="status-results">[{{ status.key.id|results_link|safe }}]</span> |