// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

/// This library defines how to read a test specification from a Yaml
/// file. We expect specifications written in this format:
///
///    dependencies:
///      b: a
///      main: [b, expect]
///    flags:
///      - constant-update-2018
///    packages:
///      c: .
///      a: a
///
///
/// Where:
///   - the dependencies section describe how modules depend on one another,
///   - the flags section show what flags are needed to run that specific test,
///   - the packages section is used to create a package structure on top of the
///     declared modules.
///
/// When defining dependencies:
///   - Each name corresponds to a module.
///   - Module names correlate to either a file, a folder, or a package.
///   - A map entry contains all the dependencies of a module, if any.
///   - If a module has a single dependency, it can be written as a single
///     value.
///
/// When defining packages:
///   - The name corresponds to a package name, this doesn't need to match
///     the name of the module. That said, it's common for some modules
///     and packages to share their name (especially for the default set of
///     packages included by the framework, like package:expect).
///   - The value is a path to the folder containing the libraries of that
///     package.
///
/// The packages entry is optional.  If this is not specified, the test will
/// still have a default set of packages, like package:expect and package:meta.
/// If the packages entry is specified, it will be extended with the definitions
/// of the default set of packages as well. Thus, the list of packages provided
/// is expected to be disjoint with those in the default set. The default set is
/// defined directly in the code of `loader.dart`.
///
/// The logic in this library mostly treats these names as strings, separately
/// `loader.dart` is responsible for validating, attaching dependency
/// information to a set of module definitions, and resolving package paths.
///
/// The framework is agnostic of what the flags are, but at this time we only
/// use the name of experimental language features. These are then used to
/// decide what options to pass to the tools that compile and run the tests.
library;

import 'package:yaml/yaml.dart';

/// Parses [contents] containing a module dependencies specification written in
/// yaml, and returns a [TestSpecification].
TestSpecification parseTestSpecification(String contents) {
  var spec = loadYaml(contents);
  if (spec is! YamlMap) {
    return _invalidSpecification("spec is not a map");
  }
  var dependencies = spec['dependencies'];
  if (dependencies == null) {
    return _invalidSpecification("no dependencies section");
  }
  if (dependencies is! YamlMap) {
    return _invalidSpecification("dependencies is not a map");
  }

  Map<String, List<String>> normalizedMap = {};
  dependencies.forEach((key, value) {
    if (key is! String) {
      _invalidSpecification("key: '$key' is not a string");
    }
    final values = normalizedMap[key] = [];
    if (value is String) {
      values.add(value);
    } else if (value is List) {
      for (var entry in value) {
        if (entry is! String) {
          _invalidSpecification("entry: '$entry' is not a string");
        }
        values.add(entry);
      }
    } else {
      _invalidSpecification(
        "entry: '$value' is not a string or a list of strings",
      );
    }
  });

  List<String> normalizedFlags = [];
  dynamic flags = spec['flags'];
  if (flags is String) {
    normalizedFlags.add(flags);
  } else if (flags is List) {
    normalizedFlags.addAll(flags.cast<String>());
  } else if (flags != null) {
    _invalidSpecification(
      "flags: '$flags' expected to be string or list of strings",
    );
  }

  Map<String, String> normalizedPackages = {};
  final packages = spec['packages'];
  if (packages != null) {
    if (packages is Map) {
      normalizedPackages.addAll(packages.cast<String, String>());
    } else {
      _invalidSpecification("packages is not a map");
    }
  }
  return TestSpecification(normalizedFlags, normalizedMap, normalizedPackages);
}

/// Data specifying details about a modular test including dependencies and
/// flags that are necessary in order to properly run a test.
///
class TestSpecification {
  /// Set of flags necessary to properly run a test.
  ///
  /// Usually this contains flags enabling language experiments.
  final List<String> flags;

  /// Dependencies of the modules that are expected to exist on the test.
  ///
  /// Note: some values in the map may not have a corresponding key. That may be
  /// the case for modules that have no dependencies and modules that are not
  /// specified explicitly because they are added automatically by the framework
  /// (for instance, the module of `package:expect` or the sdk itself).
  final Map<String, List<String>> dependencies;

  /// Map of package name to a relative path.
  ///
  /// The paths in this map are meant to be resolved relative to the location
  /// where this test specification was defined.
  final Map<String, String> packages;

  TestSpecification(this.flags, this.dependencies, this.packages);
}

Never _invalidSpecification(String message) {
  throw InvalidSpecificationError(message);
}

class InvalidSpecificationError extends Error {
  final String message;
  InvalidSpecificationError(this.message);
  @override
  String toString() => "Invalid specification: $message";
}
