LCOV - code coverage report
Current view: top level - test-0.12.24+8/lib/src/runner/configuration - suite.dart (source / functions) Hit Total Coverage
Test: coverage.lcov Lines: 7 80 8.8 %
Date: 2017-10-10 20:17:03 Functions: 0 0 -

          Line data    Source code
       1             : // Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
       2             : // for details. All rights reserved. Use of this source code is governed by a
       3             : // BSD-style license that can be found in the LICENSE file.
       4             : 
       5             : import 'package:boolean_selector/boolean_selector.dart';
       6             : import 'package:collection/collection.dart';
       7             : 
       8             : import '../../backend/metadata.dart';
       9             : import '../../backend/operating_system.dart';
      10             : import '../../backend/platform_selector.dart';
      11             : import '../../backend/test_platform.dart';
      12             : import '../../frontend/timeout.dart';
      13             : 
      14             : /// Suite-level configuration.
      15             : ///
      16             : /// This tracks configuration that can differ from suite to suite.
      17             : class SuiteConfiguration {
      18             :   /// Empty configuration with only default values.
      19             :   ///
      20             :   /// Using this is slightly more efficient than manually constructing a new
      21             :   /// configuration with no arguments.
      22             :   static final empty = new SuiteConfiguration._();
      23             : 
      24             :   /// Whether JavaScript stack traces should be left as-is or converted to
      25             :   /// Dart-like traces.
      26           0 :   bool get jsTrace => _jsTrace ?? false;
      27             :   final bool _jsTrace;
      28             : 
      29             :   /// Whether skipped tests should be run.
      30           5 :   bool get runSkipped => _runSkipped ?? false;
      31             :   final bool _runSkipped;
      32             : 
      33             :   /// The path to a mirror of this package containing HTML that points to
      34             :   /// precompiled JS.
      35             :   ///
      36             :   /// This is used by the internal Google test runner so that test compilation
      37             :   /// can more effectively make use of Google's build tools.
      38             :   final String precompiledPath;
      39             : 
      40             :   /// Additional arguments to pass to dart2js.
      41             :   ///
      42             :   /// Note that this if multiple suites run the same JavaScript on different
      43             :   /// platforms, and they have different [dart2jsArgs], only one (undefined)
      44             :   /// suite's arguments will be used.
      45             :   final List<String> dart2jsArgs;
      46             : 
      47             :   /// The patterns to match against test names to decide which to run, or `null`
      48             :   /// if all tests should be run.
      49             :   ///
      50             :   /// All patterns must match in order for a test to be run.
      51             :   final Set<Pattern> patterns;
      52             : 
      53             :   /// The set of platforms on which to run tests.
      54           0 :   List<TestPlatform> get platforms => _platforms ?? const [TestPlatform.vm];
      55             :   final List<TestPlatform> _platforms;
      56             : 
      57             :   /// Only run tests whose tags match this selector.
      58             :   ///
      59             :   /// When [merge]d, this is intersected with the other configuration's included
      60             :   /// tags.
      61             :   final BooleanSelector includeTags;
      62             : 
      63             :   /// Do not run tests whose tags match this selector.
      64             :   ///
      65             :   /// When [merge]d, this is unioned with the other configuration's
      66             :   /// excluded tags.
      67             :   final BooleanSelector excludeTags;
      68             : 
      69             :   /// Configuration for particular tags.
      70             :   ///
      71             :   /// The keys are tag selectors, and the values are configurations for tests
      72             :   /// whose tags match those selectors.
      73             :   final Map<BooleanSelector, SuiteConfiguration> tags;
      74             : 
      75             :   /// Configuration for particular platforms.
      76             :   ///
      77             :   /// The keys are platform selectors, and the values are configurations for
      78             :   /// those platforms. These configuration should only contain test-level
      79             :   /// configuration fields, but that isn't enforced.
      80             :   final Map<PlatformSelector, SuiteConfiguration> onPlatform;
      81             : 
      82             :   /// The global test metadata derived from this configuration.
      83             :   Metadata get metadata {
      84           0 :     if (tags.isEmpty && onPlatform.isEmpty) return _metadata;
      85           0 :     return _metadata.change(
      86           0 :         forTag: mapMap(tags, value: (_, config) => config.metadata),
      87           0 :         onPlatform: mapMap(onPlatform, value: (_, config) => config.metadata));
      88             :   }
      89             : 
      90             :   final Metadata _metadata;
      91             : 
      92             :   /// The set of tags that have been declared in any way in this configuration.
      93             :   Set<String> get knownTags {
      94           0 :     if (_knownTags != null) return _knownTags;
      95             : 
      96           0 :     var known = includeTags.variables.toSet()
      97           0 :       ..addAll(excludeTags.variables)
      98           0 :       ..addAll(_metadata.tags);
      99             : 
     100           0 :     for (var selector in tags.keys) {
     101           0 :       known.addAll(selector.variables);
     102             :     }
     103             : 
     104           0 :     for (var configuration in _children) {
     105           0 :       known.addAll(configuration.knownTags);
     106             :     }
     107             : 
     108           0 :     _knownTags = new UnmodifiableSetView(known);
     109           0 :     return _knownTags;
     110             :   }
     111             : 
     112             :   Set<String> _knownTags;
     113             : 
     114             :   /// All child configurations of [this] that may be selected under various
     115             :   /// circumstances.
     116             :   Iterable<SuiteConfiguration> get _children sync* {
     117           0 :     yield* tags.values;
     118           0 :     yield* onPlatform.values;
     119             :   }
     120             : 
     121             :   factory SuiteConfiguration(
     122             :       {bool jsTrace,
     123             :       bool runSkipped,
     124             :       Iterable<String> dart2jsArgs,
     125             :       String precompiledPath,
     126             :       Iterable<Pattern> patterns,
     127             :       Iterable<TestPlatform> platforms,
     128             :       BooleanSelector includeTags,
     129             :       BooleanSelector excludeTags,
     130             :       Map<BooleanSelector, SuiteConfiguration> tags,
     131             :       Map<PlatformSelector, SuiteConfiguration> onPlatform,
     132             : 
     133             :       // Test-level configuration
     134             :       Timeout timeout,
     135             :       bool verboseTrace,
     136             :       bool chainStackTraces,
     137             :       bool skip,
     138             :       int retry,
     139             :       String skipReason,
     140             :       PlatformSelector testOn,
     141             :       Iterable<String> addTags}) {
     142           0 :     var config = new SuiteConfiguration._(
     143             :         jsTrace: jsTrace,
     144             :         runSkipped: runSkipped,
     145             :         dart2jsArgs: dart2jsArgs,
     146             :         precompiledPath: precompiledPath,
     147             :         patterns: patterns,
     148             :         platforms: platforms,
     149             :         includeTags: includeTags,
     150             :         excludeTags: excludeTags,
     151             :         tags: tags,
     152             :         onPlatform: onPlatform,
     153           0 :         metadata: new Metadata(
     154             :             timeout: timeout,
     155             :             verboseTrace: verboseTrace,
     156             :             chainStackTraces: chainStackTraces,
     157             :             skip: skip,
     158             :             retry: retry,
     159             :             skipReason: skipReason,
     160             :             testOn: testOn,
     161             :             tags: addTags));
     162           0 :     return config._resolveTags();
     163             :   }
     164             : 
     165             :   /// Creates new SuiteConfiguration.
     166             :   ///
     167             :   /// Unlike [new SuiteConfiguration], this assumes [tags] is already
     168             :   /// resolved.
     169             :   SuiteConfiguration._(
     170             :       {bool jsTrace,
     171             :       bool runSkipped,
     172             :       Iterable<String> dart2jsArgs,
     173             :       this.precompiledPath,
     174             :       Iterable<Pattern> patterns,
     175             :       Iterable<TestPlatform> platforms,
     176             :       BooleanSelector includeTags,
     177             :       BooleanSelector excludeTags,
     178             :       Map<BooleanSelector, SuiteConfiguration> tags,
     179             :       Map<PlatformSelector, SuiteConfiguration> onPlatform,
     180             :       Metadata metadata})
     181             :       : _jsTrace = jsTrace,
     182             :         _runSkipped = runSkipped,
     183           5 :         dart2jsArgs = _list(dart2jsArgs) ?? const [],
     184          10 :         patterns = new UnmodifiableSetView(patterns?.toSet() ?? new Set()),
     185           5 :         _platforms = _list(platforms),
     186             :         includeTags = includeTags ?? BooleanSelector.all,
     187             :         excludeTags = excludeTags ?? BooleanSelector.none,
     188           5 :         tags = _map(tags),
     189           5 :         onPlatform = _map(onPlatform),
     190          10 :         _metadata = metadata ?? Metadata.empty;
     191             : 
     192             :   /// Creates a new [SuiteConfiguration] that takes its configuration from
     193             :   /// [metadata].
     194             :   factory SuiteConfiguration.fromMetadata(Metadata metadata) =>
     195           0 :       new SuiteConfiguration._(
     196           0 :           tags: mapMap(metadata.forTag,
     197           0 :               value: (_, child) => new SuiteConfiguration.fromMetadata(child)),
     198           0 :           onPlatform: mapMap(metadata.onPlatform,
     199           0 :               value: (_, child) => new SuiteConfiguration.fromMetadata(child)),
     200           0 :           metadata: metadata.change(forTag: {}, onPlatform: {}));
     201             : 
     202             :   /// Returns an unmodifiable copy of [input].
     203             :   ///
     204             :   /// If [input] is `null` or empty, this returns `null`.
     205             :   static List<T> _list<T>(Iterable<T> input) {
     206             :     if (input == null) return null;
     207           0 :     var list = new List<T>.unmodifiable(input);
     208           0 :     if (list.isEmpty) return null;
     209             :     return list;
     210             :   }
     211             : 
     212             :   /// Returns an unmodifiable copy of [input] or an empty unmodifiable map.
     213             :   static Map<K, V> _map<K, V>(Map<K, V> input) {
     214           0 :     if (input == null || input.isEmpty) return const {};
     215           0 :     return new Map.unmodifiable(input);
     216             :   }
     217             : 
     218             :   /// Merges this with [other].
     219             :   ///
     220             :   /// For most fields, if both configurations have values set, [other]'s value
     221             :   /// takes precedence. However, certain fields are merged together instead.
     222             :   /// This is indicated in those fields' documentation.
     223             :   SuiteConfiguration merge(SuiteConfiguration other) {
     224           0 :     if (this == SuiteConfiguration.empty) return other;
     225           0 :     if (other == SuiteConfiguration.empty) return this;
     226             : 
     227           0 :     var config = new SuiteConfiguration._(
     228           0 :         jsTrace: other._jsTrace ?? _jsTrace,
     229           0 :         runSkipped: other._runSkipped ?? _runSkipped,
     230           0 :         dart2jsArgs: dart2jsArgs.toList()..addAll(other.dart2jsArgs),
     231           0 :         precompiledPath: other.precompiledPath ?? precompiledPath,
     232           0 :         patterns: patterns.union(other.patterns),
     233           0 :         platforms: other._platforms ?? _platforms,
     234           0 :         includeTags: includeTags.intersection(other.includeTags),
     235           0 :         excludeTags: excludeTags.union(other.excludeTags),
     236           0 :         tags: _mergeConfigMaps(tags, other.tags),
     237           0 :         onPlatform: _mergeConfigMaps(onPlatform, other.onPlatform),
     238           0 :         metadata: metadata.merge(other.metadata));
     239           0 :     return config._resolveTags();
     240             :   }
     241             : 
     242             :   /// Returns a copy of this configuration with the given fields updated.
     243             :   ///
     244             :   /// Note that unlike [merge], this has no merging behavior—the old value is
     245             :   /// always replaced by the new one.
     246             :   SuiteConfiguration change(
     247             :       {bool jsTrace,
     248             :       bool runSkipped,
     249             :       Iterable<String> dart2jsArgs,
     250             :       String precompiledPath,
     251             :       Iterable<Pattern> patterns,
     252             :       Iterable<TestPlatform> platforms,
     253             :       BooleanSelector includeTags,
     254             :       BooleanSelector excludeTags,
     255             :       Map<BooleanSelector, SuiteConfiguration> tags,
     256             :       Map<PlatformSelector, SuiteConfiguration> onPlatform,
     257             : 
     258             :       // Test-level configuration
     259             :       Timeout timeout,
     260             :       bool verboseTrace,
     261             :       bool chainStackTraces,
     262             :       bool skip,
     263             :       int retry,
     264             :       String skipReason,
     265             :       PlatformSelector testOn,
     266             :       Iterable<String> addTags}) {
     267           0 :     var config = new SuiteConfiguration._(
     268           0 :         jsTrace: jsTrace ?? _jsTrace,
     269           0 :         runSkipped: runSkipped ?? _runSkipped,
     270           0 :         dart2jsArgs: dart2jsArgs?.toList() ?? this.dart2jsArgs,
     271           0 :         precompiledPath: precompiledPath ?? this.precompiledPath,
     272           0 :         patterns: patterns ?? this.patterns,
     273           0 :         platforms: platforms ?? _platforms,
     274           0 :         includeTags: includeTags ?? this.includeTags,
     275           0 :         excludeTags: excludeTags ?? this.excludeTags,
     276           0 :         tags: tags ?? this.tags,
     277           0 :         onPlatform: onPlatform ?? this.onPlatform,
     278           0 :         metadata: _metadata.change(
     279             :             timeout: timeout,
     280             :             verboseTrace: verboseTrace,
     281             :             chainStackTraces: chainStackTraces,
     282             :             skip: skip,
     283             :             retry: retry,
     284             :             skipReason: skipReason,
     285             :             testOn: testOn,
     286             :             tags: addTags));
     287           0 :     return config._resolveTags();
     288             :   }
     289             : 
     290             :   /// Returns a copy of [this] with all platform-specific configuration from
     291             :   /// [onPlatform] resolved.
     292             :   SuiteConfiguration forPlatform(TestPlatform platform, {OperatingSystem os}) {
     293           0 :     if (onPlatform.isEmpty) return this;
     294             : 
     295             :     var config = this;
     296           0 :     onPlatform.forEach((platformSelector, platformConfig) {
     297           0 :       if (!platformSelector.evaluate(platform, os: os)) return;
     298           0 :       config = config.merge(platformConfig);
     299             :     });
     300           0 :     return config.change(onPlatform: {});
     301             :   }
     302             : 
     303             :   /// Merges two maps whose values are [SuiteConfiguration]s.
     304             :   ///
     305             :   /// Any overlapping keys in the maps have their configurations merged in the
     306             :   /// returned map.
     307             :   Map<Object, SuiteConfiguration> _mergeConfigMaps(
     308             :           Map<Object, SuiteConfiguration> map1,
     309             :           Map<Object, SuiteConfiguration> map2) =>
     310           0 :       mergeMaps(map1, map2,
     311           0 :           value: (config1, config2) => config1.merge(config2));
     312             : 
     313             :   SuiteConfiguration _resolveTags() {
     314             :     // If there's no tag-specific configuration, or if none of it applies, just
     315             :     // return the configuration as-is.
     316           0 :     if (_metadata.tags.isEmpty || tags.isEmpty) return this;
     317             : 
     318             :     // Otherwise, resolve the tag-specific components.
     319           0 :     var newTags = new Map<BooleanSelector, SuiteConfiguration>.from(tags);
     320           0 :     var merged = tags.keys.fold(empty, (merged, selector) {
     321           0 :       if (!selector.evaluate(_metadata.tags)) return merged;
     322           0 :       return merged.merge(newTags.remove(selector));
     323             :     });
     324             : 
     325           0 :     if (merged == empty) return this;
     326           0 :     return this.change(tags: newTags).merge(merged);
     327             :   }
     328             : }

Generated by: LCOV version 1.13