| Index: commit-queue/tests/reduce_test_data.py
|
| ===================================================================
|
| --- commit-queue/tests/reduce_test_data.py (revision 249146)
|
| +++ commit-queue/tests/reduce_test_data.py (working copy)
|
| @@ -1,223 +0,0 @@
|
| -#!/usr/bin/env python
|
| -# Copyright (c) 2012 The Chromium Authors. All rights reserved.
|
| -# Use of this source code is governed by a BSD-style license that can be
|
| -# found in the LICENSE file.
|
| -"""Reduce the amount of data in ../test/data/*.json"""
|
| -
|
| -import json
|
| -import logging
|
| -import optparse
|
| -import os
|
| -import re
|
| -import sys
|
| -
|
| -
|
| -class Filterer(object):
|
| - def __init__(self):
|
| - self._deleted_builds = {}
|
| - self.max_cached_builds = 10
|
| - self._allowed_builders = ('linux_clang', 'linux', 'linux_touch')
|
| -
|
| - def reset(self):
|
| - self._deleted_builds = {}
|
| -
|
| - def reduce_data(self, data):
|
| - """Reduces the amount of data sent from a server to simplify testing and the
|
| - amount of test data stored.
|
| - """
|
| - self.reset()
|
| - for line in data[:]:
|
| - original_url, original_response = line
|
| - # Unpack and filter the response.
|
| - new_url, new_response = self.filter_response(
|
| - original_url, json.loads(original_response))
|
| - if not new_url or new_response is None:
|
| - data.remove(line)
|
| - continue
|
| - # Repack the string.
|
| - line[1] = json.dumps(new_response, separators=(',',':'))
|
| - logging.info('%s length: %d -> %d' % (
|
| - new_url, len(original_response), len(line[1])))
|
| - if len(line[1]) > 20000:
|
| - logging.debug(line[1])
|
| - return data
|
| -
|
| - def filter_response(self, url, response):
|
| - """Trims a single request.
|
| -
|
| - |response| must be decoded json. Decoded json will be returned.
|
| - """
|
| - # Builders
|
| - match = re.match('.+/json/builders/(\w+)(|\?filter=1)$', url)
|
| - if match:
|
| - return url, self._filter_builder(match.group(1), response)
|
| -
|
| - match = re.match('.+/json/builders(|\?filter=1)$', url)
|
| - if match:
|
| - for builder in response.keys():
|
| - value = self._filter_builder(builder, response[builder])
|
| - if value is None:
|
| - del response[builder]
|
| - else:
|
| - response[builder] = value
|
| - return url, response
|
| -
|
| - # Pending
|
| - match = re.match('.+/json/builders/(\w+)/pendingBuilds(|\?filter=1)$', url)
|
| - if match:
|
| - assert match.group(1) in self._allowed_builders
|
| - return url, self._filter_pending(response)
|
| -
|
| - # Builds
|
| - match = re.match('.+/json/builders/(\w+)/builds/_all(|\?filter=1)$', url)
|
| - if match:
|
| - builder = match.group(1)
|
| - assert builder in self._allowed_builders, url
|
| - keys = response.keys()
|
| - keys = [int(k) for k in keys if int(k) not in self._deleted(builder)]
|
| - keys = sorted(keys)[:self.max_cached_builds]
|
| - response = dict((k, v) for k, v in response.iteritems() if int(k) in keys)
|
| - return url, response
|
| -
|
| - match = re.match('.+/json/builders/(\w+)/builds/\?(.+?)(|\&filter=1)$', url)
|
| - if match:
|
| - assert match.group(1) in self._allowed_builders
|
| - # Ignore the query, reconstruct it from what it kept.
|
| - for build in response.keys():
|
| - value = self._filter_build(response[build])
|
| - if value is None:
|
| - del response[build]
|
| - else:
|
| - response[build] = value
|
| - if not response:
|
| - return None, None
|
| - url = '%s?%s' % (
|
| - url.split('?', 1)[0],
|
| - '&'.join('select=%s' % b for b in sorted(response)))
|
| - return url, response
|
| -
|
| - match = re.match('.+/json/builders/(\w+)/builds/(\d+)(|\?filter=1)$', url)
|
| - if match:
|
| - return url, self._filter_build(response)
|
| -
|
| - # Slaves
|
| - match = re.match('.+/json/slaves/([^/]+?)(|\?filter=1)$', url)
|
| - if match:
|
| - return url, self._filter_slave(match.group(1), response)
|
| -
|
| - match = re.match('.+/json/slaves(|\?filter=1)$', url)
|
| - if match:
|
| - for slave in response.keys():
|
| - value = self._filter_slave(slave, response[slave])
|
| - if value is None:
|
| - del response[slave]
|
| - else:
|
| - response[slave] = value
|
| - return url, response
|
| -
|
| - # Project
|
| - match = re.match('.+/json/project(|\?filter=1)$', url)
|
| - if match:
|
| - return url, response
|
| -
|
| - assert False, url
|
| -
|
| - @staticmethod
|
| - def _filter_pending(pending):
|
| - """Trim pendingBuilds."""
|
| - return pending[:2]
|
| -
|
| - def _filter_builder(self, builder, response):
|
| - """Trims a builder.
|
| -
|
| - Reduces the number of cached builds.
|
| - """
|
| - # TODO(maruel): Reduce the number of slaves.
|
| - if builder not in self._allowed_builders:
|
| - return None
|
| - builds_kept = response['cachedBuilds'][-self.max_cached_builds:]
|
| - builds_discarded = response['cachedBuilds'][:-self.max_cached_builds]
|
| - assert len(builds_kept) <= self.max_cached_builds
|
| - assert (
|
| - len(builds_kept) + len(builds_discarded) ==
|
| - len(response['cachedBuilds']))
|
| - if builds_discarded:
|
| - assert min(builds_kept) > max(builds_discarded)
|
| - response['cachedBuilds'] = builds_kept
|
| - self._deleted(builder).union(int(b) for b in builds_discarded)
|
| - if response.get('currentBuilds'):
|
| - response['currentBuilds'] = [
|
| - build for build in response['currentBuilds']
|
| - if int(build) not in self._deleted(builder)
|
| - ]
|
| - if response.get('pendingBuilds', 0) > 2:
|
| - response['pendingBuilds'] = 2
|
| - return response
|
| -
|
| - def _filter_build(self, response):
|
| - """Trims a build."""
|
| - if response['builderName'] not in self._allowed_builders:
|
| - return None
|
| - if int(response['number']) in self._deleted(response['builderName']):
|
| - return None
|
| - # TODO(maruel): Fix StatusJson to not push that much logs data.
|
| - if 'logs' in response:
|
| - del response['logs']
|
| - if response.get('currentStep') and response['currentStep'].get('logs'):
|
| - del response['currentStep']['logs']
|
| - for step in response['steps']:
|
| - if 'logs' in step:
|
| - del step['logs']
|
| - return response
|
| -
|
| - def _filter_slave(self, _slave, response):
|
| - """Trims a slave."""
|
| - if response.get('builders'):
|
| - for builder in response['builders'].keys():
|
| - if not builder in self._allowed_builders:
|
| - del response['builders'][builder]
|
| - if not response['builders']:
|
| - return None
|
| - if response.get('builderName'):
|
| - if not response['builderName'] in self._allowed_builders:
|
| - return None
|
| - if response.get('runningBuilds'):
|
| - for i, build in enumerate(response['runningBuilds'][:]):
|
| - value = self._filter_build(build)
|
| - if value is None:
|
| - response['runningBuilds'].remove(build)
|
| - else:
|
| - response['runningBuilds'][i] = value
|
| - return response
|
| -
|
| - def _deleted(self, builder):
|
| - return self._deleted_builds.get(builder, set())
|
| -
|
| -
|
| -def main():
|
| - parser = optparse.OptionParser(
|
| - description=sys.modules['__main__'].__doc__)
|
| - parser.add_option('-v', '--verbose', action='count', default=0)
|
| - parser.add_option('-d', '--dry-run', action='store_true')
|
| - options, args = parser.parse_args()
|
| - if args:
|
| - parser.error('Unsupported args: %s' % args)
|
| - logging.basicConfig(
|
| - level=[logging.WARNING, logging.INFO, logging.DEBUG][
|
| - min(2, options.verbose)])
|
| -
|
| - datadir = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'data')
|
| - for filename in os.listdir(datadir):
|
| - if not filename.endswith('.json') or filename.endswith('_expected.json'):
|
| - continue
|
| - filepath = os.path.join(datadir, filename)
|
| - print 'Processing %s' % filename
|
| - data = json.load(open(filepath))
|
| - data = Filterer().reduce_data(data)
|
| - if not options.dry_run:
|
| - json.dump(data, open(filepath, 'w'), separators=(',',':'))
|
| - return 0
|
| -
|
| -
|
| -if __name__ == '__main__':
|
| - sys.exit(main())
|
|
|