| OLD | NEW |
| (Empty) |
| 1 # Copyright 2015 The Chromium Authors. All rights reserved. | |
| 2 # Use of this source code is governed by a BSD-style license that can be | |
| 3 # found in the LICENSE file. | |
| 4 | |
| 5 from datetime import datetime | |
| 6 import json | |
| 7 import logging | |
| 8 import os | |
| 9 import re | |
| 10 | |
| 11 import main | |
| 12 from model.record import Record | |
| 13 from third_party.testing_utils import testing | |
| 14 | |
| 15 class PatchTimelineDataTest(testing.AppengineTestCase): | |
| 16 app_module = main.app | |
| 17 | |
| 18 def test_patch_timeline_data_simple(self): | |
| 19 events = self._test_patch('real_patch_simple') | |
| 20 self.assertEqual(events, [{ | |
| 21 'name': 'Attempt 1', | |
| 22 'cat': 'Patch Progress', | |
| 23 'ph': 'B', | |
| 24 'ts': 1434395516000184, | |
| 25 'pid': 'Attempt 1', | |
| 26 'tid': 'Patch Progress', | |
| 27 'cname': 'cq_build_attempt_running', | |
| 28 'args': {}, | |
| 29 }, { | |
| 30 'name': 'Test-Trybot', | |
| 31 'cat': 'client.skia.fyi', | |
| 32 'ph': 'B', | |
| 33 'ts': 1434395520503088, | |
| 34 'pid': 'Attempt 1', | |
| 35 'tid': 'Test-Trybot', | |
| 36 'cname': 'cq_build_running', | |
| 37 'args': { | |
| 38 'build_url': ('http://build.chromium.org/p/client.skia.fyi/builders/' | |
| 39 'Test-Trybot/builds/794'), | |
| 40 }, | |
| 41 }, { | |
| 42 'name': 'Test-Trybot', | |
| 43 'cat': 'client.skia.fyi', | |
| 44 'ph': 'E', | |
| 45 'ts': 1434395577891760, | |
| 46 'pid': 'Attempt 1', | |
| 47 'tid': 'Test-Trybot', | |
| 48 'cname': 'cq_build_passed', | |
| 49 'args': { | |
| 50 'build_url': ('http://build.chromium.org/p/client.skia.fyi/builders/' | |
| 51 'Test-Trybot/builds/794'), | |
| 52 }, | |
| 53 }, { | |
| 54 'name': 'Patch Committing', | |
| 55 'cat': 'Patch Progress', | |
| 56 'ph': 'B', | |
| 57 'ts': 1434395579639639, | |
| 58 'pid': 'Attempt 1', | |
| 59 'tid': 'Patch Progress', | |
| 60 'cname': 'cq_build_attempt_running', | |
| 61 'args': {}, | |
| 62 }, { | |
| 63 'name': 'Patch Committing', | |
| 64 'cat': 'Patch Progress', | |
| 65 'ph': 'E', | |
| 66 'ts': 1434395584564138, | |
| 67 'pid': 'Attempt 1', | |
| 68 'tid': 'Patch Progress', | |
| 69 'cname': 'cq_build_attempt_passed', | |
| 70 'args': {}, | |
| 71 }, { | |
| 72 'name': 'Attempt 1', | |
| 73 'cat': 'Patch Progress', | |
| 74 'ph': 'E', | |
| 75 'ts': 1434395584564362, | |
| 76 'pid': 'Attempt 1', | |
| 77 'tid': 'Patch Progress', | |
| 78 'cname': 'cq_build_attempt_passed', | |
| 79 'args': { | |
| 80 'action': 'patch_stop', | |
| 81 }, | |
| 82 }]) | |
| 83 | |
| 84 def test_patch_timeline_data_multiple_attempts(self): | |
| 85 events = self._test_patch('real_patch_multiple_attempts') | |
| 86 self.assertNotEqual(0, len(events)) | |
| 87 bCount = 0 | |
| 88 eCount = 0 | |
| 89 for event in events: | |
| 90 self.assertTrue(re.match('Attempt \d+', event.get('pid'))) | |
| 91 self.assertNotEqual(None, event.get('ts')) | |
| 92 if re.match('Attempt \d+', event.get('name')): | |
| 93 # Patch Progress bar | |
| 94 self.assertEqual(event.get('name'), event.get('pid')) | |
| 95 self.assertEqual('Patch Progress', event.get('tid')) | |
| 96 elif re.match('test_presubmit', event.get('name')): | |
| 97 # Builder bar | |
| 98 self.assertEqual('test_presubmit', event.get('tid')) | |
| 99 else: | |
| 100 # Committing Progress | |
| 101 self.assertEqual('Patch Committing', event.get('name')) | |
| 102 self.assertEqual('Patch Progress', event.get('tid')) | |
| 103 if event.get('ph') == 'B': | |
| 104 bCount += 1 | |
| 105 if event.get('ph') == 'E': | |
| 106 eCount += 1 | |
| 107 self.assertEquals(bCount, eCount) | |
| 108 | |
| 109 def test_patch_timeline_increasing_timestamps(self): | |
| 110 events = self._test_patch('real_patch_multiple_attempts') | |
| 111 self.assertNotEqual(0, len(events)) | |
| 112 previous_ts = events[0].get('ts') | |
| 113 for event in events: | |
| 114 self.assertTrue(previous_ts <= event.get('ts')) | |
| 115 previous_ts = event.get('ts') | |
| 116 | |
| 117 def test_patch_timeline_data_cq_buggy(self): | |
| 118 events = self._test_patch('patch_cq_buggy') | |
| 119 self.assertNotEqual(0, len(events)) | |
| 120 for event in events: | |
| 121 self.assertTrue(re.match('Attempt \d+', event.get('pid'))) | |
| 122 self.assertNotEqual(None, event.get('ts')) | |
| 123 if re.match('Attempt \d+', event.get('name')): | |
| 124 # Patch Progress bar | |
| 125 self.assertEqual(event.get('name'), event.get('pid')) | |
| 126 self.assertEqual('Patch Progress', event.get('tid')) | |
| 127 elif re.match('Test-Trybot', event.get('name')): | |
| 128 # Builder bar | |
| 129 self.assertEqual('Test-Trybot', event.get('tid')) | |
| 130 self.assertEqual('I', event.get('ph')) | |
| 131 else: | |
| 132 # Committing Progress | |
| 133 self.assertEqual('Patch Committing', event.get('name')) | |
| 134 self.assertEqual('Patch Progress', event.get('tid')) | |
| 135 | |
| 136 def test_patch_timeline_data_failed(self): | |
| 137 events = self._test_patch('patch_failed') | |
| 138 self.assertNotEqual(0, len(events)) | |
| 139 bCount = 0 | |
| 140 eCount = 0 | |
| 141 for event in events: | |
| 142 self.assertTrue(re.match('Attempt \d+', event.get('pid'))) | |
| 143 self.assertNotEqual(None, event.get('ts')) | |
| 144 if re.match('Attempt \d+', event.get('name')): | |
| 145 # Patch Progress bar | |
| 146 self.assertEqual(event.get('name'), event.get('pid')) | |
| 147 self.assertEqual('Patch Progress', event.get('tid')) | |
| 148 else: | |
| 149 # There should be no commits on failure. | |
| 150 self.assertNotEqual('Patch Committing', event.get('name')) | |
| 151 # Don't check builders because multiples are used. | |
| 152 if event.get('ph') == 'B': | |
| 153 bCount += 1 | |
| 154 if event.get('ph') == 'E': | |
| 155 eCount += 1 | |
| 156 self.assertEquals(bCount, eCount) | |
| 157 | |
| 158 def _load_records(self, filename): | |
| 159 assert Record.query().count() == 0 | |
| 160 records = _load_json(filename) | |
| 161 for record in records: | |
| 162 self.mock_now(datetime.utcfromtimestamp(record['timestamp'])) | |
| 163 Record( | |
| 164 id=record['key'], | |
| 165 tags=record['tags'], | |
| 166 fields=record['fields'], | |
| 167 ).put() | |
| 168 | |
| 169 def _test_patch(self, name, issue=123456789, patchset=1): | |
| 170 self._load_records('%s.json' % name) | |
| 171 response = self.test_app.get( | |
| 172 '/patch-timeline-data/%s/%s' % (issue, patchset)) | |
| 173 summary = json.loads(response.body) | |
| 174 logging.debug(json.dumps(summary, indent=2)) | |
| 175 return summary | |
| 176 | |
| 177 | |
| 178 def _load_json(filename): | |
| 179 path = os.path.join(os.path.dirname(__file__), 'resources', filename) | |
| 180 return json.loads(open(path).read()) | |
| OLD | NEW |