2 # Copyright (C) 2012 Google Inc. All rights reserved.
4 # Redistribution and use in source and binary forms, with or without
5 # modification, are permitted provided that the following conditions are
8 # * Redistributions of source code must retain the above copyright
9 # notice, this list of conditions and the following disclaimer.
10 # * Redistributions in binary form must reproduce the above
11 # copyright notice, this list of conditions and the following disclaimer
12 # in the documentation and/or other materials provided with the
14 # * Neither the name of Google Inc. nor the names of its
15 # contributors may be used to endorse or promote products derived from
16 # this software without specific prior written permission.
18 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 from google.appengine.ext import db
35 from controller import schedule_runs_update
36 from controller import schedule_dashboard_update
37 from controller import schedule_manifest_update
38 from models import Build
39 from models import ReportLog
40 from models import Test
41 from models import TestResult
42 from models import create_in_transaction_with_numeric_id_holder
45 class ReportProcessHandler(webapp2.RequestHandler):
47 self.response.headers['Content-Type'] = 'text/plain; charset=utf-8'
49 log_id = int(self.request.get('id', 0))
51 log = ReportLog.get_by_id(log_id)
52 if not log or not log.commit:
53 self.response.out.write("Not processed")
57 platform = log.platform()
58 build = self._create_build_if_possible(log, branch, platform)
60 for test_name, result in log.results().iteritems():
61 test = self._add_test_if_needed(test_name, branch, platform)
62 self._add_test_result_if_needed(test_name, build, result)
63 schedule_runs_update(test.id, branch.id, platform.id)
65 log = ReportLog.get(log.key())
68 # We need to update dashboard and manifest because they are affected by the existance of test results
69 schedule_dashboard_update()
70 schedule_manifest_update()
72 self.response.out.write('OK')
74 def _create_build_if_possible(self, log, branch, platform):
75 builder = log.builder()
76 key_name = builder.name + ':' + str(int(time.mktime(log.timestamp().timetuple())))
78 return Build.get_or_insert(key_name, branch=branch, platform=platform, builder=builder, buildNumber=log.build_number(),
79 timestamp=log.timestamp(), revision=log.webkit_revision(), chromiumRevision=log.chromium_revision())
81 def _add_test_if_needed(self, test_name, branch, platform):
84 test = Test.get_by_key_name(test_name)
87 test = Test(id=id, name=test_name, key_name=test_name)
89 if branch.key() not in test.branches:
90 test.branches.append(branch.key())
91 if platform.key() not in test.platforms:
92 test.platforms.append(platform.key())
95 return create_in_transaction_with_numeric_id_holder(execute) or Test.get_by_key_name(test_name)
97 def _add_test_result_if_needed(self, test_name, build, result):
98 key_name = TestResult.key_name(build, test_name)
100 def _float_or_none(dictionary, key):
101 value = dictionary.get(key)
106 if not isinstance(result, dict):
107 return TestResult.get_or_insert(key_name, name=test_name, build=build, value=float(result))
109 return TestResult.get_or_insert(key_name, name=test_name, build=build, value=float(result['avg']),
110 valueMedian=_float_or_none(result, 'median'), valueStdev=_float_or_none(result, 'stdev'),
111 valueMin=_float_or_none(result, 'min'), valueMax=_float_or_none(result, 'max'))