tool_subsharding.dart 2.98 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'dart:convert';
import 'dart:io';

class TestSpecs {

  TestSpecs({
    required this.path,
    required this.startTime,
  });

  final String path;
  int startTime;
  int? _endTime;

19
  int get milliseconds => endTime - startTime;
20 21 22 23 24

  set endTime(int value) {
    _endTime = value;
  }

25
  int get endTime => _endTime ?? 0;
26 27 28 29 30 31 32 33

  String toJson() {
    return json.encode(
      <String, String>{'path': path, 'runtime': milliseconds.toString()}
    );
  }
}

34 35 36 37 38 39
class TestFileReporterResults {
  TestFileReporterResults._({
    required this.allTestSpecs,
    required this.hasFailedTests,
    required this.errors,
  });
40

41 42 43 44
  /// Intended to parse the output file of `dart test --file-reporter json:file_name
  factory TestFileReporterResults.fromFile(File metrics) {
    if (!metrics.existsSync()) {
      throw Exception('${metrics.path} does not exist');
45
    }
46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68

    final Map<int, TestSpecs> testSpecs = <int, TestSpecs>{};
    bool hasFailedTests = true;
    final List<String> errors = <String>[];

    for (final String metric in metrics.readAsLinesSync()) {
      final Map<String, Object?> entry = json.decode(metric) as Map<String, Object?>;
      if (entry.containsKey('suite')) {
        final Map<String, Object?> suite = entry['suite']! as Map<String, Object?>;
        addTestSpec(suite, entry['time']! as int, testSpecs);
      } else if (isMetricDone(entry, testSpecs)) {
        final Map<String, Object?> group = entry['group']! as Map<String, Object?>;
        final int suiteID = group['suiteID']! as int;
        addMetricDone(suiteID, entry['time']! as int, testSpecs);
      } else if (entry.containsKey('error')) {
        final String stackTrace = entry.containsKey('stackTrace') ? entry['stackTrace']! as String : '';
        errors.add('${entry['error']}\n $stackTrace');
      } else if (entry.containsKey('success') && entry['success'] == true) {
        hasFailedTests = false;
      }
    }

    return TestFileReporterResults._(allTestSpecs: testSpecs, hasFailedTests: hasFailedTests, errors: errors);
69 70
  }

71 72 73 74 75 76 77 78 79 80
  final Map<int, TestSpecs> allTestSpecs;
  final bool hasFailedTests;
  final List<String> errors;


  static void addTestSpec(Map<String, Object?> suite, int time, Map<int, TestSpecs> allTestSpecs) {
    allTestSpecs[suite['id']! as int] = TestSpecs(
      path: suite['path']! as String,
      startTime: time,
    );
81 82
  }

83 84 85 86 87 88 89 90 91 92 93
  static void addMetricDone(int suiteID, int time, Map<int, TestSpecs> allTestSpecs) {
    final TestSpecs testSpec = allTestSpecs[suiteID]!;
    testSpec.endTime = time;
  }

  static bool isMetricDone(Map<String, Object?> entry, Map<int, TestSpecs> allTestSpecs) {
    if (entry.containsKey('group') && entry['type']! as String == 'group') {
      final Map<String, Object?> group = entry['group']! as Map<String, Object?>;
      return allTestSpecs.containsKey(group['suiteID']! as int);
    }
    return false;
94 95
  }
}