xref: /aosp_15_r20/external/libchrome/build/find_isolated_tests.py (revision 635a864187cb8b6c713ff48b7e790a6b21769273)
1*635a8641SAndroid Build Coastguard Worker#!/usr/bin/env python
2*635a8641SAndroid Build Coastguard Worker# Copyright 2014 The Chromium Authors. All rights reserved.
3*635a8641SAndroid Build Coastguard Worker# Use of this source code is governed by a BSD-style license that can be
4*635a8641SAndroid Build Coastguard Worker# found in the LICENSE file.
5*635a8641SAndroid Build Coastguard Worker
6*635a8641SAndroid Build Coastguard Worker"""Scans build output directory for .isolated files, calculates their SHA1
7*635a8641SAndroid Build Coastguard Workerhashes, stores final list in JSON document and then removes *.isolated files
8*635a8641SAndroid Build Coastguard Workerfound (to ensure no stale *.isolated stay around on the next build).
9*635a8641SAndroid Build Coastguard Worker
10*635a8641SAndroid Build Coastguard WorkerUsed to figure out what tests were build in isolated mode to trigger these
11*635a8641SAndroid Build Coastguard Workertests to run on swarming.
12*635a8641SAndroid Build Coastguard Worker
13*635a8641SAndroid Build Coastguard WorkerFor more info see:
14*635a8641SAndroid Build Coastguard Workerhttps://sites.google.com/a/chromium.org/dev/developers/testing/isolated-testing
15*635a8641SAndroid Build Coastguard Worker"""
16*635a8641SAndroid Build Coastguard Worker
17*635a8641SAndroid Build Coastguard Workerimport glob
18*635a8641SAndroid Build Coastguard Workerimport hashlib
19*635a8641SAndroid Build Coastguard Workerimport json
20*635a8641SAndroid Build Coastguard Workerimport optparse
21*635a8641SAndroid Build Coastguard Workerimport os
22*635a8641SAndroid Build Coastguard Workerimport re
23*635a8641SAndroid Build Coastguard Workerimport sys
24*635a8641SAndroid Build Coastguard Worker
25*635a8641SAndroid Build Coastguard Worker
26*635a8641SAndroid Build Coastguard Workerdef hash_file(filepath):
27*635a8641SAndroid Build Coastguard Worker  """Calculates the hash of a file without reading it all in memory at once."""
28*635a8641SAndroid Build Coastguard Worker  digest = hashlib.sha1()
29*635a8641SAndroid Build Coastguard Worker  with open(filepath, 'rb') as f:
30*635a8641SAndroid Build Coastguard Worker    while True:
31*635a8641SAndroid Build Coastguard Worker      chunk = f.read(1024*1024)
32*635a8641SAndroid Build Coastguard Worker      if not chunk:
33*635a8641SAndroid Build Coastguard Worker        break
34*635a8641SAndroid Build Coastguard Worker      digest.update(chunk)
35*635a8641SAndroid Build Coastguard Worker  return digest.hexdigest()
36*635a8641SAndroid Build Coastguard Worker
37*635a8641SAndroid Build Coastguard Worker
38*635a8641SAndroid Build Coastguard Workerdef main():
39*635a8641SAndroid Build Coastguard Worker  parser = optparse.OptionParser(
40*635a8641SAndroid Build Coastguard Worker      usage='%prog --build-dir <path> --output-json <path>',
41*635a8641SAndroid Build Coastguard Worker      description=sys.modules[__name__].__doc__)
42*635a8641SAndroid Build Coastguard Worker  parser.add_option(
43*635a8641SAndroid Build Coastguard Worker      '--build-dir',
44*635a8641SAndroid Build Coastguard Worker      help='Path to a directory to search for *.isolated files.')
45*635a8641SAndroid Build Coastguard Worker  parser.add_option(
46*635a8641SAndroid Build Coastguard Worker      '--output-json',
47*635a8641SAndroid Build Coastguard Worker      help='File to dump JSON results into.')
48*635a8641SAndroid Build Coastguard Worker
49*635a8641SAndroid Build Coastguard Worker  options, _ = parser.parse_args()
50*635a8641SAndroid Build Coastguard Worker  if not options.build_dir:
51*635a8641SAndroid Build Coastguard Worker    parser.error('--build-dir option is required')
52*635a8641SAndroid Build Coastguard Worker  if not options.output_json:
53*635a8641SAndroid Build Coastguard Worker    parser.error('--output-json option is required')
54*635a8641SAndroid Build Coastguard Worker
55*635a8641SAndroid Build Coastguard Worker  result = {}
56*635a8641SAndroid Build Coastguard Worker
57*635a8641SAndroid Build Coastguard Worker  # Get the file hash values and output the pair.
58*635a8641SAndroid Build Coastguard Worker  pattern = os.path.join(options.build_dir, '*.isolated')
59*635a8641SAndroid Build Coastguard Worker  for filepath in sorted(glob.glob(pattern)):
60*635a8641SAndroid Build Coastguard Worker    test_name = os.path.splitext(os.path.basename(filepath))[0]
61*635a8641SAndroid Build Coastguard Worker    if re.match(r'^.+?\.\d$', test_name):
62*635a8641SAndroid Build Coastguard Worker      # It's a split .isolated file, e.g. foo.0.isolated. Ignore these.
63*635a8641SAndroid Build Coastguard Worker      continue
64*635a8641SAndroid Build Coastguard Worker
65*635a8641SAndroid Build Coastguard Worker    # TODO(csharp): Remove deletion once the isolate tracked dependencies are
66*635a8641SAndroid Build Coastguard Worker    # inputs for the isolated files.
67*635a8641SAndroid Build Coastguard Worker    sha1_hash = hash_file(filepath)
68*635a8641SAndroid Build Coastguard Worker    os.remove(filepath)
69*635a8641SAndroid Build Coastguard Worker    result[test_name] = sha1_hash
70*635a8641SAndroid Build Coastguard Worker
71*635a8641SAndroid Build Coastguard Worker  with open(options.output_json, 'wb') as f:
72*635a8641SAndroid Build Coastguard Worker    json.dump(result, f)
73*635a8641SAndroid Build Coastguard Worker
74*635a8641SAndroid Build Coastguard Worker  return 0
75*635a8641SAndroid Build Coastguard Worker
76*635a8641SAndroid Build Coastguard Worker
77*635a8641SAndroid Build Coastguard Workerif __name__ == '__main__':
78*635a8641SAndroid Build Coastguard Worker  sys.exit(main())
79